using UnityEngine;
using System.Collections;


public class TreeNode  {
	
	public int x; 
	public int y;
	public int height;
	public int width;
	public TreeNode leftChild;
	public TreeNode rightChild;
	private TreeNode parent;
	public static int ratio; 
	private int minSize = 50;
	public int roomX = 0;
	public int roomY = 0;
	public int roomWidth;
	public int roomHeight;
	public bool horizontal;
	public static int counter = 1;
	public static int minRoomSize;
	public static int maxRoomSize;
	
	
	
	public TreeNode(int pX, int pY, int pWidth, int pHeight)
	{
		this.x = pX;
		this.y = pY;
		this.height = pHeight;
		this.width = pWidth;
		leftChild = null;
		rightChild = null;
		parent = null;
	}
	
	public bool split()
	{
		if( leftChild != null)
		{
			leftChild.split();
			rightChild.split();
			return true;
		}
		else
		{
			horizontal = TorF();//need to make a random function for this (done)
			int max = (horizontal ? height : width) - minSize;
			if(max < minSize)
			{
				minSize /= 2;
				max += minSize;
			}
			int split = RndInt(minSize, max);//random function here as well(done)
		
			TreeNode []listA;
			if(horizontal)
			{
				leftChild = new TreeNode(x, y, width, split);
				rightChild = new TreeNode(x, y + split, width, height - split);
				Buttons.list[counter] = leftChild;
				counter++;
				Buttons.list[counter] = rightChild;
				counter++;
				listA = Buttons.list;
				Buttons.list = new TreeNode[listA.Length + 2];
				for(int i = 0; i < listA.Length; i++)
				{
					Buttons.list[i] = listA[i];
				}
			}
			else
			{
				leftChild = new TreeNode(x, y, split, height);
				rightChild = new TreeNode(x + split, y, width - split, height);
				Buttons.list[counter]=leftChild;
				counter++;
				Buttons.list[counter] = rightChild;
				counter++;
				listA = Buttons.list;
				Buttons.list = new TreeNode[listA.Length + 2];
				for(int i = 0; i < listA.Length; i++)
				{
					Buttons.list[i] = listA[i];
				}
			}
		
			rightChild.parent = this;
			leftChild.parent = this;
		
			return true;
		}
	}
	
	public void generateRooms()//need to finish(done)
	{
		if(leftChild != null)
		{
			leftChild.generateRooms();
			rightChild.generateRooms();
		}
		else
		{
			if(parent != null)
			{
				if(parent.horizontal)//will ensure an overlap between sister node rooms
				{
					int min = this.width/2 + 1;
					if(min < Buttons.minRoomSize)
					{
						min = Buttons.minRoomSize;
					}
					roomX = Random.Range(this.x + 1, this.x + this.width - 1 - min);
					roomY = RndInt(this.y + 1, this.y + this.height - (Buttons.minRoomSize + 1));
					roomWidth = Random.Range(min, (int)(((this.x + this.width) *(Buttons.maxRoomSize/100.0))- 1) - this.roomX);
					roomHeight = Random.Range(Buttons.minRoomSize, (int)((this.height - (roomY - y))*(Buttons.maxRoomSize/100.0)) - 1 );
				}
				else
				{
					int min = this.height/2 + 1;
					if(min < Buttons.minRoomSize)
					{
						min = Buttons.minRoomSize;
					}
					roomX = Random.Range(this.x + 1, this.x + this.width - (Buttons.minRoomSize + 1));
					roomY = Random.Range(this.y + 1, this.y + this.height - 1 - min);
					roomWidth = Random.Range(Buttons.minRoomSize, (int)((this.width - (roomX - x))*(Buttons.maxRoomSize/100.0)) - 1);
					roomHeight = Random.Range(min, (int)(((this.y + this.height) * (Buttons.maxRoomSize/100.0)) - 1) - this.roomY);
				}
			}
			else
			{
				int min = this.width/2 + 1;
				roomX = Random.Range(x + 1, width - 1 - min);
				roomY = Random.Range(y + 1, height - 1 - min);
				roomWidth = Random.Range(min, (x + width - 1) - roomX);
				roomHeight = Random.Range(min, (y + height - 1) - roomY);
			}
		}
	}
	
	public void generateCorridors(int index)
	{
		if(index == counter) index = index/2 - 1;
		
		if(Buttons.list[index] != null)
		{
			int leftMin, rightMin, leftMax, rightMax;
			int minBound, maxBound;
		
			if(Buttons.list[index].horizontal)
			{
				if(Buttons.list[index].rightChild.rightChild == null)
				{
					leftMin = Buttons.list[index].leftChild.roomX;
					rightMin = Buttons.list[index].rightChild.roomX;
					leftMax = (Buttons.list[index].leftChild.roomX + Buttons.list[index].leftChild.roomWidth);
					rightMax = (Buttons.list[index].rightChild.roomX + Buttons.list[index].rightChild.roomWidth);
			
					minBound = (leftMin < rightMin ? rightMin : leftMin);
					maxBound = (leftMax > rightMax ? rightMax - 2 : leftMax - 2);
			
					Buttons.list[index].roomX = RndInt(minBound, maxBound);
					Buttons.list[index].roomY = Buttons.list[index].leftChild.roomY + Buttons.list[index].leftChild.roomHeight;
					Buttons.list[index].roomWidth = 2;
					Buttons.list[index].roomHeight = Buttons.list[index].rightChild.roomY - Buttons.list[index].roomY;
				}
				else
				{
					leftMin = Buttons.list[index].leftChild.GetMinHor();
					rightMin = Buttons.list[index].rightChild.GetMinHor();
					leftMax = Buttons.list[index].leftChild.GetMaxHor();
					rightMax = Buttons.list[index].rightChild.GetMaxHor();
			
					minBound = (leftMin < rightMin ? rightMin : leftMin);
					maxBound = (leftMax > rightMax ? rightMax - 2 : leftMax - 2);
			
					Buttons.list[index].roomX = RndInt(minBound, maxBound);
					Buttons.list[index].roomY = Buttons.list[index].SearchLeftHor(Buttons.list[index].roomX, index);
					Buttons.list[index].roomWidth = 2;
					//Buttons.list[index].roomHeight = 20;
					Buttons.list[index].roomHeight = Buttons.list[index].SearchRightHor(Buttons.list[index].roomX, index) - Buttons.list[index].roomY;
				}
			}
			else
			{
				if(Buttons.list[index].rightChild.rightChild == null)
				{
					leftMin = Buttons.list[index].leftChild.roomY;
					rightMin = Buttons.list[index].rightChild.roomY;
					leftMax = (Buttons.list[index].leftChild.roomY + Buttons.list[index].leftChild.roomHeight);
					rightMax = (Buttons.list[index].rightChild.roomY + Buttons.list[index].rightChild.roomHeight);
			
					minBound = (leftMin < rightMin ? rightMin : leftMin);
					maxBound = (leftMax > rightMax ? rightMax -2 : leftMax -2);
			
					Buttons.list[index].roomY = RndInt(minBound, maxBound);
					Buttons.list[index].roomX = Buttons.list[index].leftChild.roomX + Buttons.list[index].leftChild.roomWidth;
					Buttons.list[index].roomHeight = 2;
					Buttons.list[index].roomWidth = Buttons.list[index].rightChild.roomX - Buttons.list[index].roomX;
				}
				else
				{
					leftMin = Buttons.list[index].leftChild.GetMinVert();
					rightMin = Buttons.list[index].rightChild.GetMinVert();
					leftMax = Buttons.list[index].leftChild.GetMaxVert();
					rightMax = Buttons.list[index].rightChild.GetMaxVert();
			
					minBound = (leftMin < rightMin ? rightMin : leftMin);
					maxBound = (leftMax > rightMax ? rightMax -2 : leftMax -2);
			
					Buttons.list[index].roomY = RndInt(minBound, maxBound);
					Buttons.list[index].roomX = Buttons.list[index].SearchLeftVert(Buttons.list[index].roomY, index);
					Buttons.list[index].roomHeight = 2;
					Buttons.list[index].roomWidth = Buttons.list[index].SearchRightVert(Buttons.list[index].roomY, index) - Buttons.list[index].roomX;
				}
			}
			
			generateCorridors(index - 1);
		}
		
		
	}
	
	private bool TorF()
	{
		int rnd = Random.Range(0, 1000);
		if( rnd > 500 && (float)height/(float)width > 1.0/(float)ratio)
		{
			return true;
		}
		else if((float)width/(float)height > 1.0/(float)ratio)
		{
			return false;
		}
		else
		{
			return true;
		}
	}
	
	private int RndInt(int min, int max)
	{
		return Random.Range(min, max);
	}
	
		private int GetMinHor()
	{
		TreeNode cur = this;
		int min = Buttons.list[0].x + Buttons.list[0].width;
		while(cur != null)
		{
			
			if(min > cur.roomX)
			{
				min = cur.roomX;
			}
			cur = cur.leftChild;
		}
		return min;
	}
	
	private int GetMaxHor()
	{
		TreeNode cur = this;
		int max = Buttons.list[0].x;
		while(cur != null)
		{
			
			if(max < cur.roomX + cur.roomWidth)
			{
				max = cur.roomX + cur.roomWidth;
			}
			cur = cur.rightChild;
		}
		return max;
	}
	
	private int GetMinVert()
	{
		TreeNode cur = this;
		int min = Buttons.list[0].y + Buttons.list[0].height;
		while(cur != null)
		{
			
			if(min > cur.roomY)
			{
				min = cur.roomY;
			}
			cur = cur.leftChild;
		}
		return min;
	}
	
	private int GetMaxVert()
	{
		TreeNode cur = this;
		int max = Buttons.list[0].y;
		while(cur != null)
		{
			
			if(max < cur.roomY + cur.roomHeight)
			{
				max = cur.roomY + cur.roomHeight;
			}
			cur = cur.rightChild;
		}
		return max;
	}
	
	private int SearchLeftHor(int corX, int pIndex)
	{
		int yNeed = Buttons.list[0].y ;
		int repeat = 1;
		if(this.leftChild.roomX <= corX && corX < this.leftChild.roomX + this.leftChild.roomWidth)
			{
				if(yNeed <= this.leftChild.roomY + this.leftChild.roomHeight)
				{
					yNeed = this.leftChild.roomY + this.leftChild.roomHeight;
				}
			}
		for(int i = (pIndex * 2 + 1) * 2 + 1; i < counter; i = i * 2 +1)
		{
			repeat *= 2;
			for(int j = 0; j < repeat; j++)
			{
				if(Buttons.list[i + j].roomX <= corX && corX < Buttons.list[i + j].roomX + Buttons.list[i + j].roomWidth)
				{
					if(yNeed <= Buttons.list[i + j].roomY + Buttons.list[i + j].roomHeight)
					{
						yNeed = Buttons.list[i + j].roomY + Buttons.list[i + j].roomHeight;
					}
				}
			}
		}
		
		return yNeed;
	}
	
	private int SearchRightHor(int corX, int pIndex)
	{
		int yNeed = Buttons.list[0].y + Buttons.list[0].height;
		int repeat = 1;
		if(this.rightChild.roomX <= corX && corX < this.rightChild.roomX + this.rightChild.roomWidth)
		{
			if(yNeed >= this.rightChild.roomY + this.rightChild.roomHeight)
			{
				yNeed = this.rightChild.roomY + this.rightChild.roomHeight;
			}
		}
		for(int i = (pIndex * 2 + 2) * 2 + 1; i < counter; i = i * 2 +1)
		{
			repeat *= 2;
			for(int j = 0; j < repeat; j++)
			{
				if(Buttons.list[i + j].roomX <= corX && corX < Buttons.list[i + j].roomX + Buttons.list[i + j].roomWidth)
				{
					if(yNeed >= Buttons.list[i + j].roomY)
					{
						yNeed = Buttons.list[i + j].roomY;
					}
				}
			}
		}
		
		return yNeed;
	}
	
	private int SearchLeftVert(int corY, int pIndex)
	{
		int xNeed = Buttons.list[0].x ;
		int repeat = 1;
		if(this.leftChild.roomY <= corY && corY < this.leftChild.roomY + this.leftChild.roomHeight)
			{
				if(xNeed <= this.leftChild.roomX + this.leftChild.roomWidth)
				{
					xNeed = this.leftChild.roomX + this.leftChild.roomWidth;
				}
			}
		for(int i = (pIndex * 2 + 1) * 2 + 1; i < counter; i = i * 2 +1)
		{
			repeat *= 2;
			for(int j = 0; j < repeat; j++)
			{
				if(Buttons.list[i + j].roomY <= corY && corY < Buttons.list[i + j].roomY + Buttons.list[i + j].roomHeight)
				{
					if(xNeed <= Buttons.list[i + j].roomX + Buttons.list[i + j].roomWidth)
					{
						xNeed = Buttons.list[i + j].roomX + Buttons.list[i + j].roomWidth;
					}
				}
			}
		}
		
		return xNeed;
	}
	
	private int SearchRightVert(int corY, int pIndex)
	{
		int xNeed = Buttons.list[0].x + Buttons.list[0].width;
		int repeat = 1;
		if(this.rightChild.roomY <= corY && corY < this.rightChild.roomY + this.rightChild.roomHeight)
		{
			if(xNeed >= this.rightChild.roomX + this.rightChild.roomWidth)
			{
				xNeed = this.rightChild.roomX + this.rightChild.roomWidth;
			}
		}
		for(int i = (pIndex * 2 + 2) * 2 + 1; i < counter; i = i * 2 +1)
		{
			repeat *= 2;
			for(int j = 0; j < repeat; j++)
			{
				if(Buttons.list[i + j].roomY <= corY && corY < Buttons.list[i + j].roomY + Buttons.list[i + j].roomHeight)
				{
					if(xNeed >= Buttons.list[i + j].roomX)
					{
						xNeed = Buttons.list[i + j].roomX;
					}
				}
			}
		}
		
		return xNeed;
	}
}